/****************************************************************
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.     *
 *                                                              *
 * Copyright (C) 2009, Jun Li All rights reserved.              *
 * More about Jun{                                              *
 * Homepage: http://www.jpxx.org/                               *
 * Email   : lijun@jpxx.org                                     *
 * }                                                            *
 * SOFTWARE ENGINEERING COLLEGE OF SICHUAN UNIVERSITY           *
 *                                                              *
 ****************************************************************/
package org.jpxx.web.project;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jpxx.util.FileUtils;
import org.jpxx.util.JarBuilder;
import org.jpxx.web.Constants;

/**
 * 给工程打包Jar
 * 
 * @author Jun Li lijun@jpxx.org (http://www.jpxx.org)
 * @version 1.0.0 $org.jpxx.web.project.ProjectJar.java $ $ Date: 2009-5-14 $
 */
public class ProjectJar {

	private Logger log = Logger.getLogger(ProjectJar.class);
	private String libPath = Constants.CLASSPATH + "lib" + File.separator;
	private String binPath = Constants.PROJECT_PATH + "bin" + File.separator;
	private String targetPath = binPath + ".target" + File.separator;
	private List<Dependency> filter = null;

	/**
	 * 给项目创建jar。
	 * 
	 * @return 返回生成jar的路径
	 */
	public String[] create() {
		Project project[] = getProject();

		List<String> jar = new ArrayList<String>();
		for (int i = 0; i < project.length; i++) {
			try {

				String name = project[i].name + ".jar";
				JarBuilder jb = new JarBuilder(libPath + name);
				jb.build(project[i].classesPath);
				jar.add(libPath + name);

				log.debug("create jar: " + libPath + name);

			} catch (Exception e) {
				e.printStackTrace();
				log.error("create jar failed. ........................");
			}
		}
		return (String[]) jar.toArray(new String[0]);
	}

	/**
	 * 得到项目所有的子项目。
	 * 
	 * @return
	 */
	private Project[] getProject() {
		LayerEnum[] layer = Constants.SYSTEM_LAYER;
		if (layer == null) {
			return null;
		}

		List<Project> list = new ArrayList<Project>();
		for (int i = 0; i < layer.length; i++) {
			String layerPath = Constants.PROJECT_PATH + Constants.PROJECT_NAME
					+ File.separator + layer[i].toString().toLowerCase()
					+ File.separator;

			String name = Constants.PROJECT_NAME + "-"
					+ layer[i].toString().toLowerCase();
			File files[] = new File(layerPath).listFiles();
			if (files != null) {
				for (int j = 0; j < files.length; j++) {

					File f = files[j];
					// 找子工程
					if (f.isDirectory() && !f.getName().startsWith(".")) {
						String projectPath = layerPath + f.getName()
								+ File.separator;

						String projectName = name + "-" + f.getName();
						// classes文件目录
						String classesDir = projectPath + "target"
								+ File.separator + "classes" + File.separator;

						Project p = new Project();
						p.classesPath = classesDir;
						p.name = projectName;
						File temp = new File(classesDir);
						if (temp != null && temp.exists()) {
							list.add(p);
						}
					}
				}
			}
		}

		return (Project[]) list.toArray(new Project[0]);
	}

	@SuppressWarnings("unchecked")
	public String[] getAll() {

		String pom = Constants.PROJECT_PATH + "pom.xml";

		String m2Path = System.getProperty("user.home") + File.separator
				+ ".m2" + File.separator + "repository";

		Document doc = null;

		List<String> jarList = new ArrayList<String>();
		try {
			SAXReader reader = new SAXReader();
			doc = reader.read(new File(pom));

			log.info("parse pom: " + pom);

			Element root = doc.getRootElement();

			Element dependencyManagement = root.element("dependencyManagement");
			if (dependencyManagement == null) {
				return null;
			}
			Element dependencies = dependencyManagement.element("dependencies");
			//
			if (dependencies == null) {
				return null;
			}

			List<Element> list = dependencies.elements("dependency");

			for (Iterator<Element> i = list.iterator(); i.hasNext();) {
				try {
					Element e = i.next();
					String groupId = e.elementText("groupId").trim();
					String artifactId = e.elementText("artifactId").trim();
					if (containsDependency(groupId, artifactId)) {
						continue;
					}

					String version = e.elementText("version").trim();

					String temp = groupId.replace(".", File.separator);
					String jar = m2Path + File.separator + temp
							+ File.separator + artifactId + File.separator
							+ version + File.separator + artifactId + "-"
							+ version + ".jar";

					FileUtils.copyFile(jar, libPath);

					File f = new File(jar);
					if (f.exists()) {
						jarList.add(jar);
						log.debug("load jar with maven2: " + jar);
					}

				} catch (Exception e) {
					continue;
				}
			}

			// 项目打包
			String[] jars = this.create();
			if (jars != null)
				for (int i = 0; i < jars.length; i++) {
					FileUtils.copyFile(jars[i], targetPath + "WEB-INF"
							+ File.separator + "lib" + File.separator);
					File f = new File(jars[i]);
					if (f.exists()) {
						jarList.add(jars[i]);
						log.debug("load jar with maven2: " + jars[i]);
					}
				}

		} catch (Exception ex) {
			ex.printStackTrace();
			log.error(ex);
		}
		return (String[]) jarList.toArray(new String[0]);
	}

	private boolean containsDependency(String groupId, String artifactId) {
		if (groupId == null || artifactId == null) {
			return false;
		}
		groupId = groupId.trim();
		artifactId = artifactId.trim();

		if (filter == null) {
			filter = getDependencyFilter();
		}
		for (int i = 0; i < filter.size(); i++) {
			Dependency d = filter.get(i);
			if (d.groupId.equals(groupId) && d.artifactId.equals(artifactId)) {
				return true;
			}
		}
		return false;
	}

	private List<Dependency> getDependencyFilter() {
		List<Dependency> filter = new ArrayList<Dependency>();

		if (Constants.PROJECT_DEPENDENCY_FILTER != null
				&& !Constants.PROJECT_DEPENDENCY_FILTER.equals("")) {
			String[] dependency = Constants.PROJECT_DEPENDENCY_FILTER
					.split(";");
			for (int i = 0; i < dependency.length; i++) {
				try {
					String[] temp = dependency[i].split(",");
					Dependency d = new Dependency();
					d.groupId = temp[0].trim();
					d.artifactId = temp[1].trim();
					filter.add(d);
					log.debug("Dependency " + d.groupId + " " + d.artifactId
							+ " will be filtered when creates WAR.");
				} catch (Exception e) {
					log.error(dependency[i]
							+ "error, must be [groupId,artifactId]");
				}
			}
		}

		return filter;
	}

	private static class Dependency {
		private String groupId;
		private String artifactId;
	}

	private static class Project {
		private String classesPath;
		private String name;
	}
}
